package com.zlsy.thread.lock.reentrantlock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author zhouliang
 * @date 2020/8/5 20:33
 * 演示ReentrantReadWriteLock头节点不是写锁就可以插队的现象
 */
public class Upgrading {

    private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(false);

    private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();

    private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();

    private static void readUpgrading() {
        System.out.println(Thread.currentThread().getName() + "开始尝试获取读锁！");
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "得到读锁，正在读取。");
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "升级会代码阻塞");
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + "获取到了写锁，升级成功！");
        } finally {
            readLock.unlock();
            System.out.println(Thread.currentThread().getName() + "释放读锁！");
        }
    }


    private static void writeDownGrading() {
        System.err.println(Thread.currentThread().getName() + "开始尝试获取写锁！");
        writeLock.lock();
        try {
            System.err.println(Thread.currentThread().getName() + "得到写锁，正在写入。");
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + "在不释放写锁的情况下，直接获取读锁，成功降级。");
        } finally {
            readLock.unlock();
            System.err.println(Thread.currentThread().getName() + "释放写锁！");
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
//        System.out.println("先演示降级是可以的。");
//        Thread thread = new Thread(() -> writeDownGrading(), "thread1");
//        thread.start();

        System.out.println("演示升级是不行的。");
        Thread thread = new Thread(() -> readUpgrading(), "thread2");
        thread.start();
    }
}
